package com.hs.shirodemo2.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
class ShiroConfig {
    /**
     * 开启注解
     * @author 郭敖
     * @date 10:02 2023/8/21
     * @param securityManager
     * @description
     * @return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager  securityManager){
        AuthorizationAttributeSourceAdvisor   advisor=new  AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return   advisor;
    }

    /**
     * 开启代理
     * @author 郭敖
     * @date 10:03 2023/8/21
     * @return org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
        return new  DefaultAdvisorAutoProxyCreator();
    }

    @Bean("ehCacheManager")
    public EhCacheManager getEhcachemanager(){
        return   new  EhCacheManager();
    }

    /**
     * 创建自定义realm
     * @author 郭敖
     * @date 10:03 2023/8/21
     * @return com.hs.shirodemo01.config.UserRealm
     */
    @Bean("userRealm") // 名称
    public UserRealm getRealm() {
        UserRealm realm = new UserRealm();
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //加密方式
        matcher.setHashAlgorithmName("md5");
        matcher.setStoredCredentialsHexEncoded(true);
        //散列次数
        matcher.setHashIterations(2);
        realm.setCredentialsMatcher(matcher);
        return realm;
    }

    /**
     * 记住我
     */
    @Bean
    public SimpleCookie getSimpleCookie(){
        SimpleCookie simpleCookie= new SimpleCookie();
        simpleCookie.setHttpOnly(true);
        //7天
        simpleCookie.setName("rememberMe");
        simpleCookie.setMaxAge(604800);

        return  simpleCookie;
    }

    /**
     * 创建记住我安全管理器
     * @param simpleCookie
     * @return org.apache.shiro.web.mgt.CookieRememberMeManager
     */
    @Bean
    public CookieRememberMeManager getCookieRememberMeManager(SimpleCookie  simpleCookie){
        CookieRememberMeManager  rememberMeManager=new CookieRememberMeManager();
        rememberMeManager.setCookie(simpleCookie);
        //设置统一密钥，防止重启密钥发生变化导致记住我验证不通过
        rememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return  rememberMeManager;
    }

    /**
     * 会话管理：DefaultWebSessionManager 会话管理器
     */
    @Bean
    public DefaultWebSessionManager getDefaultWebSessionManager(){
        DefaultWebSessionManager   sessionManager=new MySessionManager();
        // session的失效时长，单位毫秒
        //sessionManager.setGlobalSessionTimeout(7*24*60*60*1000);
        //30分钟会话过期
        sessionManager.setGlobalSessionTimeout(30*60*1000);
        // 删除失效的session
        sessionManager.setDeleteInvalidSessions(true);
        return   sessionManager;
    }



    /**
     *  创建 安全管理器
     *  securityManager -> DefaultWebSecurityManager
     *  Qualifier("userRealm") 指定 Bean 的名字为 userRealm
     *  spring 默认的 BeanName 就是方法名
     *  name 属性 指定 BeanName
     * @author 郭敖
     * @description
     * @date 10:05 2023/8/21
     * @param userRealm
     * @param ehCacheManager
     * @return org.apache.shiro.web.mgt.DefaultWebSecurityManager
     */
    @Bean("securityManager")
    public DefaultWebSecurityManager getSecurityManager(UserRealm  userRealm,EhCacheManager ehCacheManager,DefaultWebSessionManager defaultWebSessionManager){
        DefaultWebSecurityManager  securityManager=new DefaultWebSecurityManager();
        // 注入自定义的realm
        securityManager.setRealm(userRealm);
        // 注入缓存管理
        securityManager.setCacheManager(ehCacheManager);

        //设置记住我   需要开启记住我功能时开启即可
        //securityManager.setRememberMeManager(rememberMeManager);

        //设置会话管理器
        securityManager.setSessionManager(defaultWebSessionManager);
        return  securityManager;
    }

    /**
     * 创建 shiro的 subject
     * subject -> ShiroFilterFactoryBean
     * Qualifier("securityManager") 指定 Bean 的名字为 securityManager
     * @author 郭敖
     * @date 10:07 2023/8/21
     * @description
     * @param securityManager
     * @return org.apache.shiro.spring.web.ShiroFilterFactoryBean
     */
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //注入核心安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //将重写的用户认证方法加入shiro的过滤器链  放行OPTIONS请求
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        filters.put("authc",new ShiroUserFilter());
        //filters.put("authz",new ShiroPermissionFilter());
        shiroFilterFactoryBean.setFilters(filters);
        // 设置请求的内置过滤器来进行如何校验
        Map<String,String> map = new LinkedHashMap<>();
        // 不需要登录就可以访问
        //map.put("/static/**","anon");
        map.put("/image","anon");
        map.put("/images/**","anon");
        map.put("/css/**","anon");
        map.put("/js/**","anon");
        map.put("/layui/**","anon");
        map.put("/login","anon");
        map.put("/user/upload","anon");
        map.put("/upload","anon");
        map.put("/auth/login","anon");
        map.put("/logout","logout");
        map.put("/message/**","anon");
        map.put("/index","anon");
        map.put("/welcome","anon");
        map.put("/","anon");
        // 需要登录才能访问
        map.put("/**","authc");
        // 把拦截规则放入拦截器中
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        // 设置如果没有认证跳转的页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 设置如果没有权限跳转的页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/pub/noPermitted");
        return shiroFilterFactoryBean;
    }


    /**
     * thymeleaf集成shiro
     */
    @Bean
    public ShiroDialect getShiroDialect(){
        return  new  ShiroDialect();
    }

}

